package com.kuang.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.util.IOUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kuang.blog.entity.Order;
import com.kuang.blog.entity.User;
import com.kuang.blog.mapper.OrderMapper;
import com.kuang.user.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wxy
 * @since 2023-07-04
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Override
    public List<Order> orderPage(Order orderpage) {
        return null;
    }


    @Override
    @Async("myexecutor")
    public IPage findPage(HttpServletResponse response, Integer pageSize, Integer pageNum) {
        Page page = new Page<>();
        page.setCurrent(pageNum);//当前页
        page.setSize(pageSize);//每页条数
        IPage iPage = this.page(page, null);


        System.out.println(Thread.currentThread().getName() + "当前执行 ------------------");

        List<Order> body = page.getRecords();


        /*导入数据到Excel表格中*/

        //通过工具创建writer   创建默认xls格式
        ExcelWriter writer = ExcelUtil.getWriter("E:/upload/Excel/" + pageNum + ".xls");//如果想要在网页上下载的方式.就不需要添加本地存储的路径
        //自定义标题别名
//        writer.addHeaderAlias("id", "数据编号");
//        writer.addHeaderAlias("oName", "数据名称");

        //合并单元格 后的标题行
//        writer.merge(2, "订单数据,每页一万条");

        //一次性写出内容   使用默认样式  强制输出标题
        writer.write(body);

//
//        fileList.add(new File("E:/upload/Excel/" + pageNum + ".xls"));


//        response.setContentType("application/vnd.ms-excel;charset=utf-8");//test.xls是弹出下裁对话框的文件名，不能为中文中文境自行编码
//        response.setHeader("Content-Disposition", "attachment;filename=order.xls");
//        ServletOutputStream out = null;
//        try {
////
//            out = response.getOutputStream();
//            writer.flush(out, true);
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            writer.close();//一定要关流 , 否则会出现一些错误
//        }
//        IoUtil.close(out);
//        BufferedOutputStream outputStream = this.onzip();
        return iPage;//注释掉的是将表格在网页上去下载下来(优质)      或者是下载到本地就只需要加上本地存储的路径就可以了
    }


    /**
     * 多线程生成excel,压缩excel,进行浏览器下载
     *
     * @param zipPath   zip路径  //自定义 本地存放zip路径
     * @param excelPath excel路径   //自定义 本地存放excel目录路径
     * @param response  响应
     * @return {@link Boolean}
     */
    @Override
    public Boolean addExcel(String zipPath, String excelDirectoryPath, HttpServletResponse response) {

        File excelDirectory = new File(excelDirectoryPath);
        //判断本地有没有生成的垃圾文件有就删除
        if (ObjectUtil.isNotEmpty(excelDirectory)) {
            //删除生成在本地的多余文件
            this.deleteFile(excelDirectoryPath);
        }

        //生成excel需要的数据,将数据转成execl文件放到本地文件夹:E:/upload/Excel/xxx.xls
        List<File> fileList = this.getList(excelDirectoryPath);
        if (ObjectUtil.isEmpty(fileList)) {
            throw new RuntimeException("excel文件集合不能为空");
        }

        //1.将本地目录下的所有需要压缩的excel文件,进行压缩成为zip,放到本地文件夹:E:/upload/Excel/Excel.zip
        //2.将本地文件夹中的压缩好的zip文件放在浏览器中进行下载
        this.zipExcelandDownloadZip(zipPath, excelDirectoryPath, response, fileList);

        return true;
    }


    /**
     * 通过多线程将数据生成,再通过多线程将生成的数据转成为本地的excel文件
     *
     * @param excelDirectoryPath 自定义 本地存放excel目录路径
     */
    @Async("myexecutor")
    public List<File> getList(String excelDirectoryPath) {
        List<File> fileList = CollUtil.newArrayList();
        List<User> list = new ArrayList<>();
        try {
            for (int i = 0; i < 10000; i++) {
                log.info(Thread.currentThread().getName() + "线程正在执行中 .. .. . .");
                //制作假数据
                list.add(new User(1l, "ljq", null, null, null, null, i, 1));
            }
            long sum = new Date().getTime();
            for (int i = 0; i < 10; i++) {
                log.debug(Thread.currentThread().getName() + "线程正在执行中 .. .. . .");
                //通过工具创建writer   创建默认xls格式
                sum = i + 1;
                ExcelWriter writer = ExcelUtil.getWriter(excelDirectoryPath + sum + ".xls");//如果想要在网页上下载的方式.就不需要添加本地存储的路径

                //
                //            //跳过当前行，既第一行，非必须，在此演示用
                //            writer.passCurrentRow();

                //合并单元格后的标题行，使用默认标题样式
                writer.merge(4, "测试userExcel");
                fileList.add(new File(excelDirectoryPath + sum + ".xls"));

                //一次性写出内容，强制输出标题
                writer.write(list, true);
                //关闭writer，释放内存
                writer.close();
            }

        } catch (Exception e) {
            log.error("写入excel异常 : " + e.getMessage());
        }
        return fileList;
    }


    /**
     * 1.将本地目录下的所有需要压缩的excel文件,进行压缩成为zip,放到本地文件夹:E:/upload/Excel/Excel.zip
     * 2.将本地文件夹中的压缩好的zip文件放在浏览器中进行下载
     *
     * @param response 响应
     * @param fileList 文件列表
     */
    public void zipExcelandDownloadZip(String zipPath, String excelDirectoryPath, HttpServletResponse response, List<File> fileList) {
        try {
            // 压缩到的位置
//            String path = "E:/upload/Excel/Excel.zip";

            File zipFile = new File(zipPath);


            // 压缩多个文件,压缩后会将压缩临时文件删除
            ZipUtil.zip(zipFile, false, fileList.toArray(new File[fileList.size()]));

            // 将zip文件下载到浏览器
            this.download(zipPath, excelDirectoryPath, response);

        } catch (Exception e) {
            log.error("文件压缩异常", e);
        }
    }

    //通用文件下载方法
    public HttpServletResponse download(String path, String excelDirectoryPath, HttpServletResponse response) {

//        File excelDirectory = new File(excelDirectoryPath);
        // path是指欲下载的文件的路径。
        File file = new File(path);
        try {

            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            file.delete();
        }
        return response;
    }

    // 删除文件 或者 清除文件夹下的所有文件
    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.isFile())  //判断是否为文件，是，则删除
        {
            file.delete();
        } else //不为文件，则为文件夹
        {
            String[] childFilePath = file.list();//获取文件夹下所有文件相对路径
            for (String path : childFilePath) {
                deleteFile(file.getAbsoluteFile() + "/" + path);//递归，对每个都进行判断
            }
            //file.delete(); // 如果不保留文件夹本身 则执行此行代码
        }
    }


    @Override
    @Async("myexecutor")
    public void uploadMP4(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();//获取文件原名称
        String path = "F:\\upload\\mvn\\" + originalFilename;
        System.out.println(Thread.currentThread().getName() + "线程正在执行中 .. .. . .");
        try {
            file.transferTo(new File(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
